#include "sph_vector.h"

// sph_vector::sph_vector(double theta, double phi) takes a theta and phi argument
// and converts to cartesian coordinates
sph_vector::sph_vector(double theta, double phi)
{
	x = cos(phi)*sin(theta);
	y = sin(phi)*sin(theta);
	z = cos(theta);
}

// sph_vector::sph_vector(double x, double y, double z) constructs a spherical vector using
// cartesian coordinates
sph_vector::sph_vector(double x,double y, double z)
{
	this->x = x;
	this->y = y;
	this->z = z;
}

// sph_vector::sph_vector() is a null intializer, initalizing to the zero vector
sph_vector::sph_vector()
{
	x = 0;
	y = 0;
	z = 0;
}

double sph_vector::get_theta()
{
	double ret = acos(z/norm());

	return ret;
}

double sph_vector::get_phi()
{
	double ret = atan2(y,x);

	return ret;
}


// sph_vector::norm() returns the norm of the vector
double sph_vector::norm()
{
	double n = sqrt(x*x + y*y + z*z);
	
	return n;
}

// overloads the + operator to give standard vector addition

sph_vector sph_vector::operator+ (sph_vector b)
{
    sph_vector ret = sph_vector(x + b.get_x(),y + b.get_y(), z + b.get_z());

	return ret;
}

// overloads the * operator to give standard multiplication by a scalar

sph_vector sph_vector::operator* (double b)
{
	sph_vector ret = sph_vector(b*x,b*y,b*z);

	return ret;
}


// double euc_distance(sph_vector a, sph_vector b) takes two
// sph_vector objects and returns a double containing the euclidean
// distance between the 2 given vectors

double euc_distance(sph_vector a, sph_vector b)
{
    double x1 = a.get_x();
	double y1 = a.get_y();
	double z1 = a.get_z();
	double x2 = b.get_x();
	double y2 = b.get_y();
	double z2 = b.get_z();
	double dist;

	dist = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2));
	return dist;
}

// double energy(sph_vector a, sph_vector b) takes two sph_vector objects
// and computers the effective potential energy between traps located
// at these points

double energy(sph_vector a, sph_vector b)
{
	double d = euc_distance(a,b);

	double energy = 1/d - 0.5 * log(d) - 0.5 * log(2.0+d);
	return energy*(-1);
}

// sph_vector dir_vector(sph_vector a, sph_vector b) computes a vector in the direction from b to a and
// normalizes this vector

sph_vector dir_vector(sph_vector a, sph_vector b)
{
	// the norm of the resulting vector is the euclidean distance of a and b
	double norm = euc_distance(a,b);

	sph_vector ret = sph_vector((a.get_x() - b.get_x())/norm, (a.get_y() - b.get_y())/norm, (a.get_z() - b.get_z())/norm);
	return ret;

}

// sph_vector force_vector(sph_vector a, sph_vector b, double weight) computers the force vector
// between two traps a,b located on the sphere.  The resultant vector is then scaled by the provided
// weight parameter

sph_vector force_vector(sph_vector a, sph_vector b, double weight)
{
	sph_vector dir = dir_vector(a,b);
	double en = energy(a,b);
	sph_vector ret = dir*(en*weight);

	return ret;
}
